package com.xxgc.demo.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.xxgc.demo.controller.annotations.CheckIdCardDate;
import com.xxgc.demo.controller.dto.UserInfoDTO;
import com.xxgc.demo.controller.enums.AppHttpCodeEnum;
import com.xxgc.demo.controller.error.myerror.UserPhoneAlreadyExistsException;
import com.xxgc.demo.controller.result.Result;
import com.xxgc.demo.controller.vo.NameAuthenticationOV;
import com.xxgc.demo.controller.vo.UserInfoPhoneVO;
import com.xxgc.demo.controller.vo.UserInfoRegisterVO;
import com.xxgc.demo.entity.Users;
import com.xxgc.demo.service.IUsersService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/***
 * @title UserLoginController
 * @author sjy
 * @version 1.0.0
 * @create 2023/9/6 14:57
 * @description 用户登录或注册接口
 **/
// @RestController = @Controller + @RequestBody
@Slf4j
@Tag(name = "用户认证中心")
@RestController
@RequestMapping("/login")
public class UserLoginController {

    //用户的业务逻辑层
    @Autowired
    private IUsersService iUsersService;

    private static final String secretKey = "Sjy123sdf23432sdf234fssAA#";

    @Operation(summary = "测试接口",description = "只是简单用来测试")
    @GetMapping("/test")
    public AppHttpCodeEnum test(){
        return null;
    }

    @Parameters({
            @Parameter(name = "uname",description = "用户名",required = true,example = "admin"),
            @Parameter(name = "pword",description = "密码",required = true,example = "123"),
    })
    @Operation(summary = "用户登录",description = "用户名密码登录")
    @PostMapping("/userLogin")
    public String userLogin(String uname, String pword, HttpServletResponse response){

        //假装查询了Service 并且返回了User对象 对象id为 133
        int userId = 133;
        //map是你要加密的内容
        Map<String, Object> map = new HashMap<String, Object>() {
            private static final long serialVersionUID = 1L;
            {
                put("uid", userId);//用户id
                put("expire_time", System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 15);//过期时间 15天
            }
        };
        //密钥
        String token = JWTUtil.createToken(map, secretKey.getBytes());
        //在响应头上面放一个token
        response.setHeader("token",token);
        return "登录成功";
    }


    @Operation(summary = "手机号密码登录",description = "手机号和密码")
    @PostMapping("/userLoginByPhone")
    public String userLoginByPhone(@RequestBody UserInfoPhoneVO userInfo){
        return null;
    }


    @Cacheable(key = "#userId",value = "user_info")
    @Parameters({
            @Parameter(name = "userId",description = "用户id",required = true,example = "1"),
    })
    @Operation(summary = "获取用户个人信息",description = "通过id获取")
    @GetMapping("/getUserInfoById/{userId}")
    public Result<UserInfoDTO> getUserInfoById(@PathVariable String userId){
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        Users users = iUsersService.getById(userId);
        BeanUtil.copyProperties(users,userInfoDTO);

        //soutv
        System.out.println("userId = " + userId);
        // 信息脱敏
        userInfoDTO.setIdCard(
                DesensitizedUtil.idCardNum(userInfoDTO.getIdCard(), 6, 4)
        );
        // 手机号脱敏
        userInfoDTO.setPhoneNumber(
                DesensitizedUtil.mobilePhone(userInfoDTO.getPhoneNumber())
        );
        // 姓名脱敏
        userInfoDTO.setUserName(
                DesensitizedUtil.chineseName(userInfoDTO.getUserName())
        );
        return Result.ok(userInfoDTO);
    }



    @Operation(summary = "获取用户个人信息Token版",description = "通过id获取Token版")
    @GetMapping("/getUserInfoByIdToken")
    public Result<UserInfoDTO> getUserInfoByIdToken(HttpServletRequest request){
        //Authorization 授权信息
        String authorization = request.getHeader("Authorization");
        //有没有
        boolean b = StrUtil.hasBlank(authorization);
        if(b){
            return Result.error().msg("请先登录");
        }
        //验证对不对
        boolean verify = JWTUtil.verify(authorization, secretKey.getBytes());
        if(!verify){//如果不对
            return Result.error().msg("登录过期，请重新登录");
        }
        //解密
        final JWT jwt = JWTUtil.parseToken(authorization);
        //获取对应字段
        String uid = jwt.getPayload("uid").toString();
        System.out.println("uid = " + uid);

        int userId = Integer.parseInt(uid);
        //------------假装去service去查询----------------------
        //soutv
        System.out.println("userId = " + userId);
        // alt + shift + L
        UserInfoDTO userInfoDTO = new UserInfoDTO("周三三", "13688889527", true, "510122200209050213", 19, LocalDateTime.now());
        // 信息脱敏
        userInfoDTO.setIdCard(
                DesensitizedUtil.idCardNum(userInfoDTO.getIdCard(), 6, 4)
        );
        // 手机号脱敏
        userInfoDTO.setPhoneNumber(
                DesensitizedUtil.mobilePhone(userInfoDTO.getPhoneNumber())
        );
        // 姓名脱敏
        userInfoDTO.setUserName(
                DesensitizedUtil.chineseName(userInfoDTO.getUserName())
        );
        return Result.ok(userInfoDTO);
    }

    // 写一个注册接口  要求字段有 姓名 手机号 密码 返回成功或失败就行
    @Operation(summary = "注册账号",description = "用户账号注册")
    @PostMapping("/registerUser")
    public Result registerUser(@RequestBody @Valid UserInfoRegisterVO userInfoRegisterVO){
        //验证手机号是否被注册
        QueryWrapper<Users> qw = new QueryWrapper<>();
        //加条件
        qw.eq("phone_number",userInfoRegisterVO.getPhoneNumber());
        Users one = iUsersService.getOne(qw);
        if(ObjectUtil.isNotNull(one)){
            //报手机号已存在异常
            throw new UserPhoneAlreadyExistsException();
        }

        //对密码进行MD5非对称加密
        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String passWord = userInfoRegisterVO.getPassWord();
        //随机盐值
        //获取UUID
        String simpleUUID = IdUtil.simpleUUID().substring(0,20);
        //加盐
        md5.setSalt(simpleUUID.getBytes());
        //算密码
        String digestHex = md5.digestHex(passWord);
        userInfoRegisterVO.setPassWord(digestHex);

        Users users = new Users();
        BeanUtil.copyProperties(userInfoRegisterVO, users);
        //盐值存数据库
        users.setSalt(simpleUUID);

        System.out.println("users = " + users.toString());
        //添加用户
        iUsersService.save(users);
        return Result.ok();
    }


    // 写一个 实名认证的身份证信息补充 （身份证号，姓名，id） 更新身份信息，返回成功或失败
    // 姓名最少两位，姓名不能出现英文
    // 身份证18位 ，身份证不能大于当前时间出生，不能是2024年出生的
    // id必填 必须是数字
    // 拦截器 - AOP
    @CheckIdCardDate
    @Operation(summary = "实名认证",description = "实名认证")
    @PostMapping("/realNameAuthentication")
    public Result realNameAuthentication(@RequestBody @Valid NameAuthenticationOV nameAuthenticationOV){
        //二次校验
        return Result.ok();
    }

    /**
     * 周末作业
     * 1、注册：创建30个用户
     * 2、分页查询用户，每页5个
     * 3、通过id逻辑删除一个用户
     * 4、通过id修改一个用户的昵称
     */
    @Parameters({
            @Parameter(name = "pageNumber",description = "第几页",required = true,example = "1"),
            @Parameter(name = "pageSize",description = "每页多少条",required = true,example = "5")
    })
    @Operation(summary = "分页查询用户",description = "分页查询")
    @GetMapping("/selectUserByPage")
    public Result<List<UserInfoDTO>> selectUserByPage(Integer pageNumber,Integer pageSize){
        //按照创建时间倒序查询
        QueryWrapper<Users> qw = new QueryWrapper<>();
        qw.orderByDesc("create_time");

        //分页器和查询条件
        Page<Users> usersPage = iUsersService.getBaseMapper()
                .selectPage(PageDTO.of(pageNumber, pageSize), qw);
        //获取分页查询的数据
        List<Users> list = usersPage.getRecords();

        //流式编程 lombda表达式
        List<UserInfoDTO> collect = list.stream().map(users -> {
            //类型转换
            UserInfoDTO userInfoDTO = new UserInfoDTO();
            BeanUtil.copyProperties(users, userInfoDTO);
            //拖敏

            //这里需要一个返回值return
            return userInfoDTO;
        }).collect(Collectors.toList());
        return Result.ok(collect).total(usersPage.getTotal());
    }

    @Parameters({
            @Parameter(name = "userId",description = "用户id",required = true)
    })
    @Operation(summary = "通过id删除用户",description = "逻辑删除")
    @GetMapping("/delUserById/{userId}")
    public Result delUserById(@PathVariable String userId){
        boolean b = iUsersService.removeById(userId);
        return b ? Result.ok() : Result.error("删除失败");
    }

    //修改用户

}
